<!--
Copyright (C) 2025 Checkmk GmbH - License: GNU General Public License v2
This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
conditions defined in the file COPYING, which is part of this source code package.
-->
<script setup lang="ts">
import { type Providers } from 'cmk-shared-typing/typescript/unified_search'
import { inject, onMounted, ref } from 'vue'

import { Api } from '@/lib/api-client'
import {
  SearchHistorySearchProvider,
  type SearchHistorySearchResult
} from '@/lib/unified-search/providers/history'
import {
  UnifiedSearchProvider,
  type UnifiedSearchProviderIdentifier,
  type UnifiedSearchResultResponse
} from '@/lib/unified-search/providers/unified'
import { SearchHistoryService } from '@/lib/unified-search/searchHistory'
import {
  type SearchProviderResult,
  UnifiedSearch,
  type UnifiedSearchResult
} from '@/lib/unified-search/unified-search'

import DefaultPopup from '@/main-menu/DefaultPopup.vue'

import UnifiedSearchFooter from './UnifiedSearchFooter.vue'
import UnifiedSearchHeader from './components/header/UnifiedSearchHeader.vue'
import UnifiedSearchStart from './components/view/UnifiedSearchStart.vue'
import UnifiedSearchTabResults from './components/view/UnifiedSearchTabResults.vue'
import UnifiedSearchWaitForResults from './components/view/UnifiedSearchWaitForResults.vue'
import { apiServiceProvider } from './providers/api'
import { initSearchUtils, provideSearchUtils } from './providers/search-utils'
import type { UnifiedSearchQueryLike } from './providers/search-utils.types'

// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const cmk: any

const searchId = 'unified-search'

const api = inject(apiServiceProvider, new Api(), true)
const searchHistoryService = new SearchHistoryService(searchId)

const props = defineProps<{
  providers: Providers
}>()

const searchProviderIdentifiers: { id: UnifiedSearchProviderIdentifier; sort: number }[] = []
if (props.providers.setup.active) {
  searchProviderIdentifiers.push({ id: 'setup', sort: props.providers.setup.sort })
}
if (props.providers.customize.active) {
  searchProviderIdentifiers.push({ id: 'customize', sort: props.providers.customize.sort })
}
if (props.providers.monitoring.active) {
  searchProviderIdentifiers.push({ id: 'monitoring', sort: props.providers.monitoring.sort })
}

const searchHistorySearchProvider = new SearchHistorySearchProvider(
  searchHistoryService as SearchHistoryService
)
const search = new UnifiedSearch(searchId, api, [
  new UnifiedSearchProvider(
    searchProviderIdentifiers.sort((a, b) => a.sort - b.sort).map((p) => p.id)
  ),
  searchHistorySearchProvider
])
search.onSearch((result?: UnifiedSearchResult) => {
  async function setSearchResults(uspr: SearchProviderResult<UnifiedSearchResultResponse>) {
    if (uspr) {
      waitForSearchResults.value = true
      const usprRes = (await uspr.result) as UnifiedSearchResultResponse

      searchResult.value = usprRes
      waitForSearchResults.value = false
    } else {
      searchResult.value = undefined
    }
  }
  async function setHistoryResults(hpr: SearchProviderResult<SearchHistorySearchResult>) {
    if (hpr) {
      const hprRes = (await hpr.result) as SearchHistorySearchResult
      historyResult.value = hprRes
    } else {
      historyResult.value = undefined
    }
  }

  void setHistoryResults(
    result?.get('search-history') as SearchProviderResult<SearchHistorySearchResult>
  )
  void setSearchResults(result?.get('unified') as SearchProviderResult<UnifiedSearchResultResponse>)
})

const searchResult = ref<UnifiedSearchResultResponse>()
const historyResult = ref<SearchHistorySearchResult>()
const waitForSearchResults = ref<boolean>(true)
const searchUtils = initSearchUtils()

searchUtils.search = search
searchUtils.history = searchHistoryService

provideSearchUtils(searchUtils)

searchUtils.onResetSearch(() => {
  searchResult.value = undefined
})

searchUtils.onCloseSearch(() => {
  cmk.popup_menu.close_popup()
})

searchUtils.input.onSetQuery((query?: UnifiedSearchQueryLike) => {
  if (query && query.input !== '/') {
    search.initSearch(query)
  }
})

searchUtils.shortCuts.onEscape(() => {
  if (
    searchUtils.input.suggestionsActive.value === false &&
    searchUtils.input.providerSelectActive.value === false
  ) {
    searchUtils.resetSearch()
    searchUtils.closeSearch()
  }
})

function showTabResults(): boolean {
  return (
    typeof searchResult.value !== 'undefined' &&
    (search.get('unified') as UnifiedSearchProvider).shouldExecuteSearch(
      searchUtils.query.toQueryLike()
    )
  )
}

onMounted(() => {
  searchUtils.shortCuts.enable()
})
</script>

<template>
  <DefaultPopup class="unified-search-root">
    <UnifiedSearchHeader> </UnifiedSearchHeader>
    <UnifiedSearchStart v-if="!showTabResults()" :history-result="historyResult">
    </UnifiedSearchStart>
    <UnifiedSearchWaitForResults v-if="waitForSearchResults && showTabResults()">
    </UnifiedSearchWaitForResults>
    <UnifiedSearchTabResults
      v-if="!waitForSearchResults && showTabResults()"
      :result="searchResult"
    >
    </UnifiedSearchTabResults>
    <UnifiedSearchFooter></UnifiedSearchFooter>
  </DefaultPopup>
</template>

<style scoped>
.unified-search-root {
  position: absolute;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 58px);
  background: var(--ux-theme-1);
  z-index: +1;
  left: 0;
  top: 58px;
  border-right: 4px solid var(--success);
  border-top-width: 0;
  width: 750px;
  max-width: 750px;
}
</style>
